(import nrc.fuzzy.*)

; Variabile globale care contin variabilele fuzzy pentru rezultatele elevului
(defglobal ?*highSchoolFuzzyVar* = (new FuzzyVariable "high-school-result" 0.0 10.0))
(defglobal ?*exam1FuzzyVar* = (new FuzzyVariable "exam-1-result" 0.0 10.0))
(defglobal ?*exam2FuzzyVar* = (new FuzzyVariable "exam-2-result" 0.0 10.0))
(defglobal ?*finalGradeFuzzyVar* = (new FuzzyVariable "final-grade-result" 0.0 10.0))

(defrule init
	=>
    (load-package nrc.fuzzy.jess.FuzzyFunctions)
    
    ; definirea termenilor
    (?*highSchoolFuzzyVar* addTerm "low" (new RightLinearFuzzySet 3.0 5.0))
    (?*highSchoolFuzzyVar* addTerm "medium" (new TrapezoidFuzzySet 4.0 5.0 7.0 8.0))
    (?*highSchoolFuzzyVar* addTerm "high" (new LeftLinearFuzzySet 7.0 9.0))
    
    (?*exam1FuzzyVar* addTerm "bad" (new RightLinearFuzzySet 5.0 7.0))
    (?*exam1FuzzyVar* addTerm "good" (new LeftLinearFuzzySet 5.0 7.0))

    (?*exam2FuzzyVar* addTerm "bad" (new RightLinearFuzzySet 5.0 7.0))
    (?*exam2FuzzyVar* addTerm "good" (new LeftLinearFuzzySet 5.0 7.0))

    (?*finalGradeFuzzyVar* addTerm "low" (new RightLinearFuzzySet 3.0 5.0))
    (?*finalGradeFuzzyVar* addTerm "medium" (new TrapezoidFuzzySet 4.0 5.0 7.0 8.0))
    (?*finalGradeFuzzyVar* addTerm "high" (new LeftLinearFuzzySet 7.0 9.0))


    
;    (assert (lowGrade (new FuzzyValue ?*highSchoolFuzzyVar* "low")))
;    (assert (mediumGrade (new FuzzyValue ?*highSchoolFuzzyVar* "medium")))
;    (assert (highGrade (new FuzzyValue ?*highSchoolFuzzyVar* "high")))

    ;valori test
    (bind ?high-school-grade-value 8.0)    
    (bind ?exam-1-grade-value 5.5)
	(bind ?exam-2-grade-value 7.0)
    
    ;declararea unei valori fuzzy de tip singleton pentru a putea efectua operatia de fuzzy-match (ambele valori trebuie sa fie neaparat fuzzy)
    (assert (highSchoolGrade (new FuzzyValue ?*highSchoolFuzzyVar* (new SingletonFuzzySet ?high-school-grade-value))))
    (assert (exam1Grade (new FuzzyValue ?*exam1FuzzyVar* (new SingletonFuzzySet ?exam-1-grade-value))))
    (assert (exam2Grade (new FuzzyValue ?*exam2FuzzyVar* (new SingletonFuzzySet ?exam-2-grade-value))))
            
)

;definirea regulilor

(defrule rule1
    (highSchoolGrade ?h&:(fuzzy-match ?h "low"))
  	(exam1Grade ?e1&:(fuzzy-match ?e1 "bad"))
    =>
    (assert (finalGrade (new FuzzyValue ?*finalGradeFuzzyVar* "low")))
)

(defrule rule2
    (highSchoolGrade ?h&:(fuzzy-match ?h "low"))
  	(exam2Grade ?e2&:(fuzzy-match ?e2 "bad"))
    =>
    (assert (finalGrade (new FuzzyValue ?*finalGradeFuzzyVar* "low")))
)

(defrule rule3
  	(exam1Grade ?e1&:(fuzzy-match ?e1 "bad"))
    (exam2Grade ?e2&:(fuzzy-match ?e2 "bad"))
    =>
    (assert (finalGrade (new FuzzyValue ?*finalGradeFuzzyVar* "low")))
)

(defrule rule4
    (highSchoolGrade ?h&:(fuzzy-match ?h "medium"))
  	(exam1Grade ?e1&:(fuzzy-match ?e1 "bad"))
    (exam2Grade ?e2&:(fuzzy-match ?e2 "good"))
    =>
    (assert (finalGrade (new FuzzyValue ?*finalGradeFuzzyVar* "medium")))
)

(defrule rule5
    (highSchoolGrade ?h&:(fuzzy-match ?h "medium"))
  	(exam1Grade ?e1&:(fuzzy-match ?e1 "good"))
    (exam2Grade ?e2&:(fuzzy-match ?e2 "bad"))
    =>
    (assert (finalGrade (new FuzzyValue ?*finalGradeFuzzyVar* "medium")))
)

(defrule rule6
    (highSchoolGrade ?h&:(fuzzy-match ?h "low"))
  	(exam1Grade ?e1&:(fuzzy-match ?e1 "good"))
    (exam2Grade ?e2&:(fuzzy-match ?e2 "good"))
    =>
    (assert (finalGrade (new FuzzyValue ?*finalGradeFuzzyVar* "medium")))
)

(defrule rule7
    (highSchoolGrade ?h&:(fuzzy-match ?h "medium"))
  	(exam1Grade ?e1&:(fuzzy-match ?e1 "good"))
        (exam2Grade ?e2&:(fuzzy-match ?e2 "good"))
    =>
    (assert (finalGrade (new FuzzyValue ?*finalGradeFuzzyVar* "high")))
)

(defrule rule8
    (highSchoolGrade ?h&:(fuzzy-match ?h "high"))
  	(exam1Grade ?e1&:(fuzzy-match ?e1 "good"))
    (exam2Grade ?e2&:(fuzzy-match ?e2 "good"))
    =>
    (assert (finalGrade (new FuzzyValue ?*finalGradeFuzzyVar* "high")))
)

(defrule print-high
    (finalGrade ?f&:(fuzzy-match ?f "high"))
    =>
    (printout t "Final grade is HIGH" crlf)
)

(defrule print-medium
    (finalGrade ?f&:(fuzzy-match ?f "medium"))
    =>
    (printout t "Final grade is MEDIUM" crlf)
)

(defrule print-low
    (finalGrade ?f&:(fuzzy-match ?f "low"))
    =>
    (printout t "Final grade is LOW" crlf)
)

;(defrule print
;    (finalGrade ?f&:(fuzzy-match ?f "high"))
;    (exam1Grade ?e1)
;    (exam2Grade ?e2)
;    =>
;    (bind ?fuzzyValuesArray (create$ ?h ?e1 ?e2))
;    (printout t (call FuzzyValue plotFuzzyValues "*+-" ?fuzzyValuesArray) crlf)
 
    
    ;    (printout t (?h toString) crlf crlf (?e1 toString) crlf crlf (?e2 toString))
    
;    (printout t "grade is high")
;)

;(defrule print-grades
;	(lowGrade ?l&:(fuzzy-match ?l "low"))
;    (mediumGrade ?m&:(fuzzy-match ?m "medium"))
;	(highGrade ?h&:(fuzzy-match ?h "high"))
;   =>
    
    
;    (bind ?fuzzyValuesArray (create$ (new FuzzyValue ?*highSchoolFuzzyVar* "low")))
;    (bind ?fuzzyValuesArray (create$ ?l ?m ?h))
;    (printout t (call FuzzyValue plotFuzzyValues "*+-" ?fuzzyValuesArray) crlf)
;)

(reset)
(run)